什么是重排,重绘?
在我还是菜菜菜鸟时,有人就问我了。你知道什么操作会引起重排吗?
当时就在想,重排是个什么东东。。。于是,Google了一下(说谷歌显的高大上点(⊙﹏⊙)b)
当然,提到重排重绘,就理所当然会提及DOM树和渲染树等等~ 这就让我们一个个慢慢道来。
高性能JavaScript里是这么说的:
“浏览器下载完页面中的所有组件————HTML标记、JavaScript、CSS、图片————之后就会解析并生成两个内部数据结构”
DOM树
表示页面结构
渲染树
表示DOM节点如何显示
DOM树和渲染树就是相互存在的一种数据结构,DOM树里每一个需要显示的节点在渲染树里至少会有一个对应的节点(当然,隐藏的DOM元素在渲染树里是没用节点的)渲染树的节点可以叫“帧”或者“盒”,可以理解为CSS里面的盒子吧,就可以把对应的页面元素理解为一个具有padding,margin,border和position(位置)的盒子。一旦这DOM树和渲染树相互构建完成之后,浏览器就可以要是显示(绘制paint)页面元素了。
可是怎么理解呢,就举个栗子吧,不知道大家画过画没,数字油画呢?就用它来说栗子:
- 比如我要画个柯南,你要想把,柯南肯定是个人吧,有眼睛,鼻子,嘴巴,耳朵各种五官吧,当然还要穿衣服吧,可以还可以把他爱人小兰画上吧。就是你画像需要显示的内容就是对应DOM树的节点,他们的集合就构成一棵DOM树吧;
- 那当你决定要画的时候,就要构造柯南的头有多大,眼睛大小之类的吧,上什么色吧,就像数字油画给你的那个有数字,不同格子填什么色的,这个格子就是可以当成渲染树的节点,那这个集合构成就是渲染树啦;
- 最后,我这个大画家就要开始作画啦,那你画到画布上的过程就是绘制painting啦,painting这个词形象生动O(∩_∩)O~
不知道这样说,清楚没呢~
所以,一旦DOM树变化,影响了页面元素的几何属性(宽高)————比如,改变了元素border或者给段落添加文字增加了行数————这样的话,浏览器就要重新计算元素的几何属性,以及其他受影响的元素。这时浏览器起作用啦,就会让渲染树受影响部分失效,进行重新计算,再重新构造渲染树,这个过程就叫做“重排热flow”,重排完成后,浏览器会把受影响部分的元素重新显示(绘制)到屏幕上,这一过程就叫做“重绘”。就这样理解嘛,活字印刷术里,你要写文字,你的文字都还没有排好,怎么进行印刷呢。
但是呢,并不是有了重排才会有重绘,就比如,你页面元素的几何属性就修改背景颜色,其他都不改,这个行为是没有触发重排的(因为没有修改元素的布局),但是浏览器需要进行一次重绘,把新的背景颜色绘制到屏幕上。
重排怎么触发(发生)?
当页面布局和几何属性改变时就需要重排。举栗子
- 添加或删除可见DOM元素,注意是可见,不可见的根本就不在渲染树上好吗;
- 元素位置改变;就如把A移动到B,B移动到A
- 元素尺寸改变(包括:padding,margin,border,width,height等属性改变时);
- 内容改变,如文本改变,或者图片被另一个不同尺寸的图片替换
- 页面渲染器初始化
- 浏览器窗口尺寸变化,这里我就有点疑问,那要是我每次缩放浏览器不都会触发吗???
- 最后,页面出现滚动条时也会触发。。。
渲染树变化的排队与刷新
因为每一次的重排都会消耗很大一部分的性能,所以,浏览器一般都会通过队列化修改并批量执行来优化重排过程。但是你可能没注意使用到一些属性,就会强制刷新队列并计划任务立马执行,就马上重排了!!!
获取布局信息的操作会强制队列刷新,所以,以下的属性尽量避免使用!
- offsetTop,offsetLeft,offsetWidth,offsetHeigt;
- scrollTop,scrollLeft,scrollWidth,scrollHeight;
- clientTop,clientLeft,clientWidth,clientHeight;
- getComputedStyle() (currentStyle in IE)
最小化重绘和重排
改变样式
改变样式时,最后就是,合并所有的改变,然后一次性处理,这样就只会修改DOM一次,做到最小化重排啦
批量修改DOM
方法有很多
- 为需要修改的节点创建备份,然后对副本进行修改,修改完成后就用它来对旧的节点进行替换
- (墙裂推荐)使用创建文档片段createDocumentFragment的方法,具体可以看我之前关于文档片段的笔记,因为这种方法产生的DOM遍历和重排次数是最少的。
嗯,重排和重绘就先这样吧。可以结合前面摘的浏览器工作流~